package com.atguigu.gmall.order.service.impl;

import com.alibaba.fastjson.JSON;
import com.atguigu.gmall.common.constant.MqConst;
import com.atguigu.gmall.common.service.RabbitService;
import com.atguigu.gmall.common.util.HttpClientUtil;
import com.atguigu.gmall.model.enums.OrderStatus;
import com.atguigu.gmall.model.enums.PaymentStatus;
import com.atguigu.gmall.model.enums.ProcessStatus;
import com.atguigu.gmall.model.order.OrderDetail;
import com.atguigu.gmall.model.order.OrderInfo;
import com.atguigu.gmall.order.mapper.OrderDetailMapper;
import com.atguigu.gmall.order.mapper.OrderInfoMapper;
import com.atguigu.gmall.order.service.OrderService;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sun.org.apache.xpath.internal.operations.Or;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class OrderServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo> implements OrderService {

    @Autowired
    private OrderInfoMapper orderInfoMapper;

    @Autowired
    private OrderDetailMapper orderDetailMapper;

    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    RabbitService rabbitService;

    @Value("${ware.url}")
    private String WARE_URL;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long saveOrderInfo(OrderInfo orderInfo) {
        orderInfo.sumTotalAmount();
        orderInfo.setOrderStatus(OrderStatus.UNPAID.name());

        String outTradeNo = "ATGUIGU"+System.currentTimeMillis()+""+new Random().nextInt(1000);
        orderInfo.setOutTradeNo(outTradeNo);
        //订单描述
        orderInfo.setTradeBody("小主订单生成中，准备就绪");
        orderInfo.setCreateTime(new Date());
        Calendar calendar = Calendar.getInstance();
        //当前系统上时间+1
        calendar.add(Calendar.DATE,1);
        orderInfo.setExpireTime(calendar.getTime());
        //辅助订单状态
        orderInfo.setProcessStatus(ProcessStatus.UNPAID.name());
        orderInfoMapper.insert(orderInfo);

        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        orderDetailList.forEach(orderDetail -> {
            orderDetail.setOrderId(orderInfo.getId());
            orderDetailMapper.insert(orderDetail);
        });

        //发送延迟队列，如果定时未支付，取消订单
        rabbitService.sendDelayMessage(MqConst.EXCHANGE_DIRECT_ORDER_CANCEL, MqConst.ROUTING_ORDER_CANCEL, orderInfo.getId(), MqConst.DELAY_TIME);
        Long orderId = orderInfo.getId();
        return orderId;
    }

    @Override //生成
    public String getTradeNo(String userId) {
        String tradeNo = UUID.randomUUID().toString();

        String tradeNoKey = "tradeNo:"+userId;
        this.redisTemplate.opsForValue().set(tradeNoKey,tradeNo);
        return tradeNo;
    }

    @Override //比较
    public Boolean checkTradeNo(String userId, String tradeNo) {

        String tradeNoKey = "tradeNo:"+userId;
        String tradeNoRedis  = (String) this.redisTemplate.opsForValue().get(tradeNoKey);
        return tradeNo.equals(tradeNoRedis);
    }

    @Override //删除
    public void delTradeNo(String userId) {
        String tradeNoKey = "tradeNo:"+userId;
        this.redisTemplate.delete(tradeNoKey);
    }

    @Override
    public Boolean checkStock(Long skuId, Integer skuNum) {
        // 远程调用http://localhost:9001/hasStock?skuId=10221&num=2
        String result = HttpClientUtil.doGet(WARE_URL + "/hasStock?skuId=" + skuId + "&num=" + skuNum);
        return "1".equals(result);
    }

    @Override
    public IPage<OrderInfo> getpage(Page<OrderInfo> pageParam, String userId) {
        IPage<OrderInfo> page = orderInfoMapper.selectPageByUserId(pageParam, userId);
        page.getRecords().stream().forEach(item -> {
            item.setOrderStatusName(OrderStatus.getStatusNameByStatus(item.getOrderStatus()));
        });
        return page;
    }

    @Override
    public void execExpiredOrder(Long orderId) {
        updateOrderStatus(orderId, ProcessStatus.CLOSED);
        rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_PAYMENT_CLOSE,MqConst.ROUTING_PAYMENT_CLOSE,orderId);
    }

    @Override
    public OrderInfo getOrderInfo(Long orderId) {
        OrderInfo orderInfo = orderInfoMapper.selectById(orderId);
        List<OrderDetail> orderidList = orderDetailMapper.selectList(new QueryWrapper<OrderDetail>().eq("order_id", orderId));

        orderInfo.setOrderDetailList(orderidList);
        return orderInfo;
    }

    @Override
    public void sendOrderStatus(Long orderId) {
        this.updateOrderStatus(orderId, ProcessStatus.NOTIFIED_WARE);

        String wareJson = initWareOrder(orderId);
        rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_WARE_STOCK,MqConst.ROUTING_WARE_STOCK,wareJson);

    }

    private String initWareOrder(Long orderId) {
        OrderInfo orderInfo = getOrderInfo(orderId);
        Map map = initWareOrder(orderInfo);
        return JSON.toJSONString(map);

    }

    public void updateOrderStatus(Long orderId, ProcessStatus paid) {

        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setId(orderId);
        orderInfo.setProcessStatus(paid.name());
        orderInfo.setOrderStatus(paid.getOrderStatus().name());

        orderInfoMapper.updateById(orderInfo);
    }

    @Override
    public Map initWareOrder(OrderInfo orderInfo) {
        HashMap<String,Object> hashMap = new HashMap<>();

        hashMap.put("orderId",orderInfo.getId());
        hashMap.put("consignee",orderInfo.getConsignee());
        hashMap.put("consigneeTel",orderInfo.getConsigneeTel());
        hashMap.put("orderComment",orderInfo.getOrderComment());
        hashMap.put("orderBody",orderInfo.getTradeBody());
        hashMap.put("deliveryAddress",orderInfo.getDeliveryAddress());
        hashMap.put("paymentWay","2");
        hashMap.put("wareId",orderInfo.getWareId());

        List<OrderDetail> mapArrayList = orderInfo.getOrderDetailList();

        List<HashMap<String,Object>> orderDetailList = mapArrayList.stream().map(orderDetail -> {
            HashMap<String, Object> orderDetailMap = new HashMap<>();
            orderDetailMap.put("skuId", orderDetail.getSkuId());
            orderDetailMap.put("skuNum", orderDetail.getSkuNum());
            orderDetailMap.put("skuName", orderDetail.getSkuName());
            return orderDetailMap;
        }).collect(Collectors.toList());
        hashMap.put("details",orderDetailList);

        return hashMap;
    }

    @Override
    @Transactional
    public List<OrderInfo> orderSplit(Long orderId, String wareSkuMap) {
        ArrayList<OrderInfo> subOrderDetailList = new ArrayList<>();
        OrderInfo orderInfoOrigin = getOrderInfo(orderId);
        List<Map> mapList = JSON.parseArray(wareSkuMap, Map.class);

        if(mapList != null){
            for (Map map : mapList) {
                String wareId = (String) map.get("wareId");
                List<String> skuIds = (List<String>) map.get("skuIds");

                OrderInfo orderInfo = new OrderInfo();
                //属性拷贝
                BeanUtils.copyProperties(orderInfoOrigin,orderInfo);
                //防止主键冲突
                orderInfo.setId(null);
                orderInfo.setParentOrderId(orderId);
                orderInfo.setWareId(wareId);

                ArrayList<OrderDetail> orderDetails = new ArrayList<>();
                //  能够找到 skuId = 23,24
                List<OrderDetail> orderDetailList = orderInfoOrigin.getOrderDetailList();
                // 表示主主订单明细中获取到子订单的明细
                if(orderDetailList != null && orderDetailList.size()>0){
                    for (OrderDetail orderDetail : orderDetailList) {
                        for (String skuId : skuIds) {
                            if(Long.parseLong(skuId) == orderDetail.getSkuId().longValue()){
                                orderDetails.add(orderDetail);
                            }
                        }
                    }
                }
                //计算总金额
                orderInfo.sumTotalAmount();
                orderInfo.setOrderDetailList(orderDetails);
                //保存总订单
                saveOrderInfo(orderInfo);
                //将子订单添加到集合中
                subOrderDetailList.add(orderInfo);
            }
        }
        //修改原始订单状态
        updateOrderStatus(orderId,ProcessStatus.SPLIT);
        return subOrderDetailList;
    }

    @Override
    public void execExpiredOrder(Long orderId, String flag) {
        updateOrderStatus(orderId,ProcessStatus.CLOSED);
        if ("2".equals(flag)) {
            // 发送消息队列，关闭支付宝的交易记录
            rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_PAYMENT_CLOSE,MqConst.ROUTING_PAYMENT_CLOSE,orderId);

        }
    }

}
